package com.jl.cloud.commom.aspect;

import com.jl.cloud.commom.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;


/**
 * 注解分布式锁AOP
 * @author liang.jun
 */
@Configuration
@Aspect
@Slf4j
public class DistributedLockAspect {



    @Pointcut("@annotation(distributedLock)")
    public void pointcut(DistributedLock distributedLock) {}

    @Around("pointcut(distributedLock)")
    public Object around(ProceedingJoinPoint jp, DistributedLock distributedLock) throws Throwable {
        String key = distributedLock.key();

        // 如果没有设置key，则使用方法类路径作为key
        if (StringUtils.isEmpty(key)) {
            key = jp.getTarget().getClass().getName() + "." + jp.getSignature().getName();
        }
        RLock lock = RedisUtils.getLock(key);
        // 尝试加锁
        if (lock.tryLock(distributedLock.waitTime(),distributedLock.leaseTime(),TimeUnit.SECONDS)) {
            try {
                return jp.proceed();
            } finally {
                lock.unlock();
            }
        } else {
            log.error("分布式锁获取失败");
            throw new Exception("锁获取失败");
        }
    }

}
